#include "Bot.h"
#include "Simulator.hh"
//#include "Order.h"
//#include "Strategy.hh"

using namespace std;

extern hive_estimator_t hive_est;



bool Bot::move_ant_if_possible(Map<double> & xreward, uLocation & from)
{
  TRACK();
  // select best valid movement if exists
  double best = xreward[from];
  uLocation best_option = from;
  for(unsigned d=0; d!=Torus::TDIRECTIONS; ++d)
      {
	uLocation to = torus.getLocation(from,d);
	if(not state.map[to].isWater
	   and state.map[to].ant == -1)
	  {
	    if(xreward[to]>best or (xreward[to]==best and rand()%2==0)) 
	      {
		best = xreward[to];
		best_option = to;
	      }
	  }
      }

    if(state.map[best_option].ant == -1)
      {
	bug << "Move: " << best << " : " << torus.to_str(from,best_option) << std::endl;
	unsigned direction = torus.getDirection(from,best_option);
	ASSERT(direction!=Torus::TDIRECTIONS);
	cout << "o " << torus.get_row(from) << " " << torus.get_col(from)
	     << " " << torus.direction_name(direction) << endl;
	state.map.at(from).ant = -1;
	from = best_option;
	state.map.at(best_option).ant = 0;
	return true;
      }
    else
      {
	return false;
      }
}



void Bot::move_ants_according_to_reward(Map<double> & xreward)
{
  TRACK();
  unsigned changes = 1;
  unsigned count = 100;
  visited.reset();
  while(changes > 0 and count!=0)
    {
      changes = 0;
      for(std::vector<uLocation>::iterator it = state.myAnts.begin(); it!=state.myAnts.end(); ++it)
	{
	  if(not visited.count(*it) and move_ant_if_possible(xreward, *it))
	    {
	      visited.insert(*it);
	      changes++;
	    }
	}
      count--;
    }
  ASSERT(count>0);

}





//constructor
Bot::Bot()
{

}

//plays a single game of Ants.
void Bot::playGame()
{
    TRACK();

    if(getrusage(RUSAGE_SELF,&meminfo) ==0)
      bug << "memory usage: " << meminfo.ru_maxrss << "KB" << std::endl;


    //reads the game parameters and sets up
    cin >> state;
    state.setup();
    strategy.init();
    hive_est.init(state.myHills,state.food);
    endTurn();

    mc.init();



    //continues making moves while the game is not over
    while(cin >> state)
    {
        state.updateNeighbourInformation();
        state.updateVisionInformation();
        makeMoves();
        endTurn();
    }
}

//makes the bots moves for the turn
void Bot::makeMoves()
{
    TRACK();

    bug << "turn " << state.turn << ":" << endl;
    bug << state << endl;



    if(getrusage(RUSAGE_SELF,&meminfo) ==0)
      bug << "memory usage: " << meminfo.ru_maxrss << "KB" << std::endl;

	
    // update food count 
    hive_est.update_hive_estimate_before_turn(state);
    
    //update our knowledge of the map and recover all known places
    memory.update_map_knowledge_before_turn(state);

#if DEBUG
    // save map
    for(uLocation loc=0; loc!=torus.size; ++loc)
      state.map_copy.at(loc) = state.map.at(loc);
#endif


    // Simulation process
    mc.init_simulations();

    unsigned n=0;
    while(state.timer.getTime() <0.9*state.turntime)
      {

	mc.begin_simulation();
	mc.make_random_moves(torus.viewRadius*5,n);
	mc.end_simulation();
	n++;
      }
    
    bug << "simulations: " << n << std::endl;
    
    if(state.turn%10==0)
      for(unsigned t = 0; t!=mc.teams.size(); ++t)
	if(not mc.teams[t].Ants.empty())
	  {
	    std::ostringstream fname;
	    fname << "turn" << state.turn << "_team" << t;
	    mc.teams[t].expected_reward.dump_to_file(fname);
	  }

    // check map
#if DEBUG
    for(uLocation loc=0; loc!=torus.size; ++loc)
      if(state.map_copy.at(loc) != state.map.at(loc))
	{
	  bug << "incoherence at " << torus.to_str(loc) << std::endl;
	  bug << "map is " << state.map.at(loc) 
	      << " instead of " << state.map_copy.at(loc) 
	      << std::endl;
	  ASSERT(state.map_copy.at(loc) == state.map.at(loc));
	}
#endif


    move_ants_according_to_reward(mc.teams[0].expected_reward);



    

#if 0
  
    // build order preferences
    Order moves;

    //picks out all possible move options weighted by expected_reward map
    for(std::vector<uLocation>::const_iterator ant_it = state.myAnts.begin();
	ant_it != state.myAnts.end(); ++ant_it)
      {
	moves.proposeAction(*ant_it,*ant_it,mc.teams.at(0).expected_reward[*ant_it]);
	for(unsigned d = 0; d!=Torus::TDIRECTIONS; ++d)
	  {
	    uLocation to(torus.getLocation(*ant_it,d));
	    if(not state.map[to].isWater)
	      moves.proposeAction(*ant_it,to,mc.teams.at(0).expected_reward[to]);
	  }
      }

    // execute best moving plan according to these options
    moves.execute(state);

#endif

	
    // try to estimate food reserve (hive)
    hive_est.update_hive_estimate_after_turn(state);

    bug << "time taken: " << state.timer.getTime() << "ms" 
	<< " hence " << state.timer.getTime()*100.0/state.turntime << "%"
	<< endl << endl;
}

//finishes the turn
void Bot::endTurn()
{
    TRACK();

    if(state.turn > 0)
        state.reset();
    state.turn++;

    cout << "go" << endl;
}
